package com.study.imageprocessing;

import java.util.Random;

import android.graphics.Bitmap;
import android.graphics.Color;

public class ProcessFunction {
	public static final int COLOR_MIN = 0x00;
	public static final int COLOR_MAX = 0xFF;

	public static Bitmap invertImage(Bitmap bmIn) {
		// create new bitmap with the same settings as source bitmap
		Bitmap bmOut = Bitmap.createBitmap(bmIn.getWidth(), bmIn.getHeight(),
				bmIn.getConfig());
		// color info
		int A, R, G, B;
		int pixelColor;
		// image size
		int height = bmIn.getHeight();
		int width = bmIn.getWidth();

		// scan through every pixel
		for (int y = 0; y < height; y++) {
			for (int x = 0; x < width; x++) {
				// get one pixel
				pixelColor = bmIn.getPixel(x, y);
				// saving alpha channel
				A = Color.alpha(pixelColor);
				// inverting byte for each R/G/B channel
				R = 255 - Color.red(pixelColor);
				G = 255 - Color.green(pixelColor);
				B = 255 - Color.blue(pixelColor);
				// set newly-inverted pixel to output image
				bmOut.setPixel(x, y, Color.argb(A, R, G, B));
			}
		}
		// return final bitmap
		return bmOut;
	}

	public static Bitmap doGreyscale(Bitmap bmIn) {
		// constant factors
		final double GS_RED = 0.299;
		final double GS_GREEN = 0.587;
		final double GS_BLUE = 0.114;

		// create output bitmap
		Bitmap bmOut = Bitmap.createBitmap(bmIn.getWidth(), bmIn.getHeight(),
				bmIn.getConfig());
		// pixel information
		int A, R, G, B;
		int pixel;

		// get image size
		int width = bmIn.getWidth();
		int height = bmIn.getHeight();

		// scan through every single pixel
		for (int x = 0; x < width; ++x) {
			for (int y = 0; y < height; ++y) {
				// get one pixel color
				pixel = bmIn.getPixel(x, y);
				// retrieve color of all channels
				A = Color.alpha(pixel);
				R = Color.red(pixel);
				G = Color.green(pixel);
				B = Color.blue(pixel);
				// take conversion up to one single value
				R = G = B = (int) (GS_RED * R + GS_GREEN * G + GS_BLUE * B);
				// set new pixel color to output bitmap
				bmOut.setPixel(x, y, Color.argb(A, R, G, B));
			}
		}
		// return final image
		return bmOut;
	}

	public static Bitmap binaryIamge(Bitmap bmIn) {
		// create output bitmap
		Bitmap bmOut = Bitmap.createBitmap(bmIn.getWidth(), bmIn.getHeight(),
				bmIn.getConfig());
		// pixel information
		int R, G, B;
		int pixel;

		// get image size
		int width = bmIn.getWidth();
		int height = bmIn.getHeight();

		// scan through every single pixel
		for (int x = 0; x < width; ++x) {
			for (int y = 0; y < height; ++y) {
				// get one pixel color
				pixel = bmIn.getPixel(x, y);
				// retrieve color of all channels
				R = Color.red(pixel);
				G = Color.green(pixel);
				B = Color.blue(pixel);
				if (B > 225 / 2) {
					B = 255;
				} else {
					B = 0;
				}
				if (G > 225 / 2) {
					G = 255;
				} else {
					G = 0;
				}
				if (R > 225 / 2) {
					R = 255;
				} else {
					R = 0;
				}
				// set new pixel color to output bitmap
				bmOut.setPixel(x, y, Color.rgb(R, G, B));
			}
		}
		// return final image
		return bmOut;
	}

	public static Bitmap applyFleaEffect(Bitmap bmIn) {
		// get image size
		int width = bmIn.getWidth();
		int height = bmIn.getHeight();
		int[] pixels = new int[width * height];
		// get pixel array from source
		bmIn.getPixels(pixels, 0, width, 0, 0, width, height);
		// a random object
		Random random = new Random();

		int index = 0;
		// iteration through pixels
		for (int y = 0; y < height; ++y) {
			for (int x = 0; x < width; ++x) {
				// get current index in 2D-matrix
				index = y * width + x;
				// get random color
				int randColor = Color.rgb(random.nextInt(COLOR_MAX),
						random.nextInt(COLOR_MAX), random.nextInt(COLOR_MAX));
				// OR
				pixels[index] |= randColor;
			}
		}
		// output bitmap
		Bitmap bmOut = Bitmap.createBitmap(width, height, bmIn.getConfig());
		bmOut.setPixels(pixels, 0, width, 0, 0, width, height);
		return bmOut;
	}

	public static Bitmap applyHueFilter(Bitmap bmIn, int level) {
		// get image size
		int width = bmIn.getWidth();
		int height = bmIn.getHeight();
		int[] pixels = new int[width * height];
		float[] HSV = new float[3];
		// get pixel array from source
		bmIn.getPixels(pixels, 0, width, 0, 0, width, height);

		int index = 0;
		// iteration through pixels
		for (int y = 0; y < height; ++y) {
			for (int x = 0; x < width; ++x) {
				// get current index in 2D-matrix
				index = y * width + x;
				// convert to HSV
				Color.colorToHSV(pixels[index], HSV);
				// increase Saturation level
				HSV[0] *= level;
				HSV[0] = (float) Math.max(0.0, Math.min(HSV[0], 360.0));
				// take color back
				pixels[index] |= Color.HSVToColor(HSV);
			}
		}
		// output bitmap
		Bitmap bmOut = Bitmap.createBitmap(width, height,
				Bitmap.Config.ARGB_8888);
		bmOut.setPixels(pixels, 0, width, 0, 0, width, height);
		return bmOut;
	}

	public static Bitmap applySnowEffect(Bitmap bmIn) {
		// get image size
		int width = bmIn.getWidth();
		int height = bmIn.getHeight();
		int[] pixels = new int[width * height];
		// get pixel array from source
		bmIn.getPixels(pixels, 0, width, 0, 0, width, height);
		// random object
		Random random = new Random();

		int R, G, B, index = 0, thresHold = 50;
		// iteration through pixels
		for (int y = 0; y < height; ++y) {
			for (int x = 0; x < width; ++x) {
				// get current index in 2D-matrix
				index = y * width + x;
				// get color
				R = Color.red(pixels[index]);
				G = Color.green(pixels[index]);
				B = Color.blue(pixels[index]);
				// generate threshold
				thresHold = random.nextInt(COLOR_MAX);
				if (R > thresHold && G > thresHold && B > thresHold) {
					pixels[index] = Color.rgb(COLOR_MAX, COLOR_MAX, COLOR_MAX);
				}
			}
		}
		// output bitmap
		Bitmap bmOut = Bitmap
				.createBitmap(width, height, Bitmap.Config.RGB_565);
		bmOut.setPixels(pixels, 0, width, 0, 0, width, height);
		return bmOut;
	}
}
